<template>
	<div class="flex">
		<el-upload accept=".xlsx,.xls" action="" :disabled="isUploading" :auto-upload="false" :show-file-list="false" :on-change="handleImport">
			<slot>
				<el-button type="primary" :icon="isUploading ? 'Loading' : 'Upload'">{{ uploadText }}</el-button>
			</slot>
		</el-upload>
		<el-button v-if="needExport" type="primary" icon="Download" @click="exportExcel">{{ exportText }}</el-button>
	</div>
</template>

<script setup lang="ts" name="MyExcel">
import { dayjs, UploadFile } from 'element-plus';
import { read, writeFileXLSX, utils } from 'xlsx';

const props = withDefaults(
		defineProps<{
			keymap: Record<string, string>;
			tableData?: Record<string, string | number>[];
			fileName?: string;
			uploadText?: string;
			exportText?: string;
			needExport?: boolean;
		}>(),
		{
			uploadText: '导入',
			exportText: '导出',
			needExport: true
		}
	),
	emit = defineEmits<{
		(e: 'upload-success', data: Record<string, any>[]): void;
	}>();

const isUploading = ref(false);

/**
 * 文件上传解析
 * @param file 文件
 */
function handleImport(file: UploadFile) {
	if (!/\.xlsx|\.xlx$/.test(file.name.toLocaleLowerCase())) {
		msgError('请上传xlsx或者xlx文件');
		return;
	}
	isUploading.value = true;
	const reader = new FileReader();
	reader.onload = (e) => {
		try {
			if (!e.target?.result) {
				isUploading.value = false;
				msgError('文件读取失败,请检查文件！');
				return;
			}
			const data = new Uint8Array(e.target.result as ArrayBuffer);
			const workbook = read(data, { type: 'array' });

			// 获取第一个工作表
			const firstSheetName = workbook.SheetNames[0];
			const worksheet = workbook.Sheets[firstSheetName];

			// 转换为JSON数据
			const jsonData = utils.sheet_to_json(worksheet, { header: 1 });

			// 获取表头
			const header = jsonData[0] as string[];
			// 获取数据
			const tableData = (jsonData.slice(1) as [string[]]).map((row) => {
				return header.reduce(
					(obj, item, i) => {
						if (props.keymap[item]) {
							obj[props.keymap[item]] = row[i] || '';
						}
						return obj;
					},
					{} as Record<string, any>
				);
			});
			emit('upload-success', tableData);
			msgSuccess('文件解析成功');
			isUploading.value = false;
		} catch (error) {
			isUploading.value = false;
			msgError('文件解析失败,请检查文件！' + error);
		}
	};
	reader.readAsArrayBuffer(file.raw!);
}

/**
 * excel文件导出
 */
function exportExcel() {
	try {
		if (!props.tableData?.length) {
			msgError('无数据可导出！');
			return;
		}
		const header = Object.keys(props.keymap),
			tableData = props.tableData.map((row) => Object.values(props.keymap).map((key) => row[key] || ''));
		const ws = utils.aoa_to_sheet([header, ...tableData]);
		const wb = utils.book_new();
		utils.book_append_sheet(wb, ws, 'Sheet1');
		writeFileXLSX(wb, `${props.fileName || dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
		msgSuccess('导出成功');
	} catch (error) {
		console.log(error);
	}
}
</script>

<style scoped lang="scss"></style>
